RAM-Wipe in dom0. Protection against Cold‑Boot Attack in Qubes

Installation and activation of dracut RAM-Wipe module to wiping memory on shutdown for protection against cold‑boot attack in Qubes.

A cold boot attack is a type of computer security attack that involves accessing sensitive information from a computer’s random access memory (RAM) after the computer has been turned off or restarted. Normally, when a computer is turned off or restarted, the data in the RAM is erased. However, with a cold boot attack, the attacker can quickly freeze the RAM before it loses its contents, and transfer RAM to another computer to read its contents. This allows the attacker to access sensitive information, such as encryption keys or login credentials, that were stored in the RAM.

RAM-Wipe module was created by the Kicksecure / Whonix devs: GitHub - Kicksecure/ram-wipe: Wipe RAM on shutdown and reboot - Cold Boot Attack Defense

RAM-Wipe has undergone a security audit: Thoughts dereferenced from the scratchpad noise. | ram-wipe: Further analysis

A similar module is used by Tails.

This is an excellent tool against cold‑boot attacks.

This guide solves the old problem of Wipe RAM on shutdown in Qubes

You will see new entries after shutdown Qubes.

It also works great and enhances Qubes security in Live‑Mode for maximum protection against forensic analysis: Qubes OS live mode. dom0 in RAM. Non-persistent Boot. Protection against forensics. Tails mode. Hardening dom0

:warning: A problem with this solution could be that the system takes too long to shutdown in critically dangerous moments (10-30 seconds). Use the solutions from this discussion to create an “emergency button” that powers off the system within a few seconds. For example, xfce4-session-logout --halt -f
Also use USB Kill Switch for Qubes OS - Physical Security Enhancement

I created a script that will build the module in a few seconds and add it to dracut.
Save the script, for example, with the name wipe.sh into /home/user/
Make the file executable. Run in terminal sudo chmod +x wipe.sh or tick the box in File Properties → Permissions → Program:
Copy file to dom0. Run it in dom0 terminal qvm-run --pass-io <qube-name> 'cat /home/user/wipe.sh' > wipe.sh
Run it with sudo: sudo ./wipe.sh

#!/bin/bash

# Script to install dracut ram-wipe module

echo "Creating dracut ram-wipe module directories and files..."

# Create module directory
mkdir /usr/lib/dracut/modules.d/40ram-wipe/

# module-setup.sh
cat > /usr/lib/dracut/modules.d/40ram-wipe/module-setup.sh << 'EOF'
#!/bin/bash
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
# ex: ts=8 sw=4 sts=4 et filetype=sh

## Copyright (C) 2023 - 2025 ENCRYPTED SUPPORT LLC <adrelanos@whonix.org>
## See the file COPYING for copying conditions.

# called by dracut
check() {
   require_binaries sync || return 1
   require_binaries sleep || return 1
   require_binaries dmsetup || return 1
   return 0
}

# called by dracut
depends() {
   return 0
}

# called by dracut
install() {
   inst_simple "/usr/libexec/ram-wipe/ram-wipe-lib.sh" "/lib/ram-wipe-lib.sh"
   inst_multiple sync
   inst_multiple sleep
   inst_multiple dmsetup
   inst_hook shutdown 40 "$moddir/wipe-ram.sh"
   inst_hook cleanup 80 "$moddir/wipe-ram-needshutdown.sh"
}

# called by dracut
installkernel() {
   return 0
}
EOF

chmod +x /usr/lib/dracut/modules.d/40ram-wipe/module-setup.sh

# wipe-ram-needshutdown.sh
cat > /usr/lib/dracut/modules.d/40ram-wipe/wipe-ram-needshutdown.sh << 'EOF'
#!/bin/sh

## Copyright (C) 2023 - 2025 ENCRYPTED SUPPORT LLC <adrelanos@whonix.org>
## See the file COPYING for copying conditions.

type getarg >/dev/null 2>&1 || . /lib/dracut-lib.sh

. /lib/ram-wipe-lib.sh

ram_wipe_check_needshutdown() {
   ## 'local' is unavailable in 'sh'.
   #local kernel_wiperam_setting

   kernel_wiperam_setting="$(getarg wiperam)"

   if [ "$kernel_wiperam_setting" = "skip" ]; then
      force_echo "wipe-ram-needshutdown.sh: Skip, because wiperam=skip kernel parameter detected, OK."
      return 0
   fi

   true "wipe-ram-needshutdown.sh: Calling dracut function need_shutdown to drop back into initramfs at shutdown, OK."
   need_shutdown

   return 0
}

ram_wipe_check_needshutdown
EOF

chmod +x /usr/lib/dracut/modules.d/40ram-wipe/wipe-ram-needshutdown.sh

# wipe-ram.sh
cat > /usr/lib/dracut/modules.d/40ram-wipe/wipe-ram.sh << 'EOF'
#!/bin/sh

## Copyright (C) 2023 - 2025 ENCRYPTED SUPPORT LLC <adrelanos@whonix.org>
## See the file COPYING for copying conditions.

## Credits:
## First version by @friedy10.
## https://github.com/friedy10/dracut/blob/master/modules.d/40sdmem/wipe.sh

## Use '.' and not 'source' in 'sh'.
. /lib/ram-wipe-lib.sh

drop_caches() {
   sync
   ## https://gitlab.tails.boum.org/tails/tails/-/blob/master/config/chroot_local-includes/usr/local/lib/initramfs-pre-shutdown-hook
   ### Ensure any remaining disk cache is erased by Linux' memory poisoning
   echo 3 > /proc/sys/vm/drop_caches
   sync
}

ram_wipe() {
   ## 'local' is unavailable in 'sh'.
   #local kernel_wiperam_setting dmsetup_actual_output dmsetup_expected_output

   ## getarg returns the last parameter only.
   kernel_wiperam_setting="$(getarg wiperam)"

   if [ "$kernel_wiperam_setting" = "skip" ]; then
      force_echo "wipe-ram.sh: Skip, because wiperam=skip kernel parameter detected, OK."
      return 0
   fi

   force_echo "wipe-ram.sh: RAM extraction attack defense... Starting RAM wipe pass during shutdown..."

   drop_caches

   force_echo "wipe-ram.sh: RAM wipe pass completed, OK."

   ## In theory might be better to check this beforehand, but the test is
   ## really fast.
   force_echo "wipe-ram.sh: Checking if there are still mounted encrypted disks..."

   ## TODO: use 'timeout'?
   dmsetup_actual_output="$(dmsetup ls --target crypt 2>&1)"
   dmsetup_expected_output="No devices found"

   if [ "$dmsetup_actual_output" = "$dmsetup_expected_output" ]; then
      force_echo "wipe-ram.sh: Success, there are no more mounted encrypted disks, OK."
   elif [ "$dmsetup_actual_output" = "" ]; then
      force_echo "wipe-ram.sh: Success, there are no more mounted encrypted disks, OK."
   else
      ## dracut should unmount the root encrypted disk cryptsetup luksClose during shutdown
      ## https://github.com/dracutdevs/dracut/issues/1888
      force_echo "\\
wipe-ram.sh: There are still mounted encrypted disks! RAM wipe incomplete!

debugging information:
dmsetup_expected_output: '$dmsetup_expected_output'
dmsetup_actual_output: '$dmsetup_actual_output'"
      ## How else could the user be informed that something is wrong?
      sleep 5
   fi
}

ram_wipe
EOF

chmod +x /usr/lib/dracut/modules.d/40ram-wipe/wipe-ram.sh

# dracut.conf.d
cat > /usr/lib/dracut/dracut.conf.d/30-ram-wipe.conf << 'EOF'
add_dracutmodules+=" ram-wipe "
EOF

# ram-wipe-lib.sh
mkdir /usr/libexec/ram-wipe
cat > /usr/libexec/ram-wipe/ram-wipe-lib.sh << 'EOF'
#!/bin/sh

## Copyright (C) 2023 - 2025 ENCRYPTED SUPPORT LLC <adrelanos@whonix.org>
## See the file COPYING for copying conditions.

## Based on:
## /usr/lib/dracut/modules.d/99base/dracut-lib.sh
if [ -z "$DRACUT_SYSTEMD" ]; then
    force_echo() {
        echo "<28>dracut INFO: $*" > /dev/kmsg
        echo "dracut INFO: $*" >&2
    }
else
    force_echo() {
        echo "INFO: $*" >&2
    }
fi
EOF

chmod +x /usr/libexec/ram-wipe/ram-wipe-lib.sh

# Update INITRAMFS
dracut --verbose --force
echo "ram-wipe module created successfully!"
6 Likes

You can use the Xen command-line option scrub-domheap if you want the memory to be cleared when the domain is destroyed.

1 Like

Studying the Xen documentation and GitHub discussions, I concluded that this parameter does not protect dom0 and Xen from a cold‑boot attack. In fact, the parameter is essentially useless in that regard, as Marmarek points out in this comment:

In this comment, Marmarik confirms that Qubes does not have complete protection against this attack and may consider possible solutions to the problem in the future:

It seems that init_on_free=1 offers more benefit for memory protection, but it is not a tool against cold‑boot attacks.

1 Like

You are not wrong, but your shutdown script also doesn’t protect against cold boot attacks. The attacker is going to hard reset the system, your script is never going to get executed.

2 Likes

Undoubtedly, attackers rely on hard reset, and it is a problem for Tails and Kicksecure. Nevertheless, it provides a guarantee in cases where the user managed to shutdown the system - for example, via a USB kill‑switch, or if police/attackers break door and user has a few seconds to press a shutdown. That’s better than not having such a tool at all, and I agree with the logic of Kicksecure and Tails. Otherwise, we could say, “Disk encryption doesn’t make sense - attackers intend to obtain a powered‑on computer with the operating system running”.

1 Like

Just for the sake of the argument: my laptop(s) take around 30s (**) from the “xfce4-session-logout --halt” to full showdown. That’s a lot of seconds. Some other delaying means are needed (like: locked drawer(?)).

** the interval is a few seconds longer with a normal “poweroff” or “systemctl poweroff”. See this thread.

1 Like

@barto

I agree with you. This is a great idea for creating an “emergency shutdown button”. My laptop shuts down relatively ~ 10 seconds, but it would be better to achieve shutdown in 3–4 seconds.
I will add a link to this discussion in the guide.

1 Like

Activator for the anti-cold boot attack in Whonix!
Run this script in dom0!
To trigger the anti-cold-boot attack, you can’t use a USB kill switch, as dom0 doesn’t accept any USB connections. So, we install the anti-cold boot attack and then go to the Qubes application menu, then Settings, and Configuration Manager, then Keyboard, and add a shortcut for an easy shutdown, like Control + Alt + Space! This way, when criminals or military personnel try to take your PC with Qubes running to attack with a cold boot attack, you can quickly and easily press Control + Alt + Space!

2 Likes

@shan-shazan-iot Good idea. Users can add a keyboard shortcut to trigger the command xfce4‑session‑logout --halt -f. I think it’s better to use a two‑key combination.

How do I prove that the RAM wipe really occurred?
How do I check the logs, which logs should I look at, and what should I be looking for to know if these anti-cold boot attack modules really worked?
How can I prove that they actually worked? Are they really functioning?
List the commands we can use to check this since the logs of dom0 are different from Ubuntu!

You can check the triggers in the ram-wipe.sh file. The memory clearing works like Tails using this command:

drop_caches() {
   sync
   ## https://gitlab.tails.boum.org/tails/tails/-/blob/master/config/chroot_local-includes/usr/local/lib/initramfs-pre-shutdown-hook
   ### Ensure any remaining disk cache is erased by Linux' memory poisoning
   echo 3 > /proc/sys/vm/drop_caches
   sync
}

This is a standard Linux kernel option for clearing the memory cache. You can look for it in the journal logs.

You won’t see these lines after shutdown if the clearing didn’t happen (for example, delete the ram-wipe-lib.sh file and those lines won’t appear after shutdown).

I try to check the logs from the journal with sudo journalctl > journalctl.txt. Entering journalctl.txt I couldn’t find anything either. With sudo journalctl | grep -i 'dracut INFO', I couldn’t find anything either! I tried all the words and full phrases from the screenshot you showed, and I didn’t detect anything in the logs… is it failing? Perhaps this is failing:

force_echo() {
echo “<28>dracut INFO: $" > /dev/kmsg
echo "dracut INFO: $
” >&2
}

And checking sudo journalctl | grep -i ‘dracut INFO’ doesn’t work! The force_echo method is being used by several scripts, but maybe it is failing… I have also added a logger for each script “message that specific script worked,” but it doesn’t work and no logs appear in the journal! What was the command or commands sudo journalctl exactly that you used, and what was the search to find the logs that the scripts were executed?

I know nothing about this protection against Cold-Boot Attack but after reading it I feel that it would be great to make it available to everyone and, as people are arguing about the time to process the RAM wipe, here would be my suggestion:

“Start menu”

  1. Shut Down
  2. Shut Down with Cold Boot Protection
  3. Restart

Thank you for this post anyway.

This memory‑poisoning operation echo 3 > /proc/sys/vm/drop_caches does not generate a log message by default. It’s a direct command to the kernel that runs silently. The kernel doesn’t log it. Therefore, the Kicksecure devs added a dracut-log indicating a successful operation. In the journal you can only see whether the module was activated or not.

1 Like